package com.cool.springcloud.config;

import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;


import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;

import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.concurrent.TimeUnit;

/**
 * 不使用 @Configuration
 * @Author ifredomvip@gmail.com
 * @Date 2022/8/18 15:39
 * @Version 1.0.0
 * @Description
 * 注解 @LoadBalancerClient(value = "CLOUD-PAYMENT-SERVICE", configuration = CustomLoadBalancerConfiguration.class)
 * //LoadBalancerClient value的值指定了在给定的load-balancer client配置下，要发送请求到哪个服务(服务id)
 **/
@LoadBalancerClients({
        @LoadBalancerClient(value = "CLOUD-PAYMENT-SERVICE", configuration = CustomLoadBalancerConfiguration.class),
        @LoadBalancerClient(value = "CLOUD-ORDER-SERVICE", configuration = CustomLoadBalancerConfiguration.class)
})
public class ApplicationContextConfig {

    /**
     * 一. Spring RestTemplate 作为负载均衡器客户端
     * 1. 默认使用JDK自带的HttpURLConnection作为底层HTTP客户端实
     * 注解含义 @LoadBalanced  让这个RestTemplate在请求时拥有客户端负载均衡的能力  //将此注解注释掉，使用自己的轮询算法不使用默认的
     * @return {@link RestTemplate}
     */
    @Bean
    @ConditionalOnMissingBean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        // 使用OKHtt实现
        System.out.println("===========RestTemplate");
        return new RestTemplate(getOkHttpRequestFactory());
    }

    /**
     * 二. Spring WebClient 作为负载均衡器客户端
     */
    @Bean
    @ConditionalOnMissingBean
    @LoadBalanced
    public WebClient.Builder loadBalancedWebClientBuilder() {
        System.out.println("===========WebClient");
        return WebClient.builder();
    }

    /**
     * 2.使用 OkHttpClient 作为底层客户端，切换 Spring RestTemplate 中实现
     *
     * 从开发人员的反馈，和网上的各种HTTP客户端性能以及易用程度评测来看
     * OkHttp 优于 Apache HttpClient
     * Apache HttpClient 优于 HttpURLConnection
     * <p>
     *
     * @return ClientHttpRequestFactory
     */
    private ClientHttpRequestFactory getOkHttpRequestFactory() {

        ConnectionPool pool = new ConnectionPool(30, 300L, TimeUnit.MINUTES);

        OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .connectionPool(pool)
                .connectTimeout(10L, TimeUnit.SECONDS)
                .readTimeout(10L, TimeUnit.SECONDS)
                .writeTimeout(10L, TimeUnit.SECONDS)
                .build();

        return new OkHttp3ClientHttpRequestFactory(okHttpClient);
    }

    /**
     * 2.使用 Apache HttpClient 作为底层客户端，切换 Spring RestTemplate 中实现
     * <p>
     *
     * @return ClientHttpRequestFactory
     */
    private ClientHttpRequestFactory getApacheHttpClientRequestFactory() {

        HttpClient httpClient = HttpClients.custom().build();

        return  new HttpComponentsClientHttpRequestFactory(httpClient);
    }



}
